package com.boyou.sytzc.utils.data

import android.content.Intent
import android.os.Bundle
import android.os.Parcelable

/**
 * 获取Intent中的参数
 * @param clazz 参数所属类型，如果是ArrayList, List, MutableList, Collection，则需要填写componentClazz参数
 * @param defaultValue 默认值，部分定义的数据类型需要必传默认参数：Boolean, Double, Float, Long, Int, Short, Char, Byte
 * @param componentClazz 数据类型中子项的数据类型，如果clazz为释义中提及的类型，则此参数为必选项
 */
fun <T> Intent.getArgument(
	clazz: Class<T>,
	argumentName: String,
	defaultValue: Any? = null,
	componentClazz: Class<*>? = null
): Any? = when {

	clazz == Bundle::class.java -> {
		when {
			hasExtra(argumentName) -> getBundleExtra(argumentName)
			extras?.containsKey(argumentName) == true -> extras?.getBundle(argumentName)
			else -> null
		}
	}

	clazz == CharSequence::class.java -> {
		(when {
			hasExtra(argumentName) -> getCharSequenceExtra(argumentName)
			extras?.containsKey(argumentName) == true -> extras?.getCharSequence(argumentName)
			else -> null
		}) ?: defaultValue as CharSequence?
	}
	clazz == String::class.java -> {
		(when {
			hasExtra(argumentName) -> getStringExtra(argumentName)
			extras?.containsKey(argumentName) == true -> extras?.getString(argumentName)
			else -> null
		}) ?: defaultValue as String?
	}

	clazz == Boolean::class.java -> {
		if (defaultValue == null) throw Exception("错误：参数defaultValue不能为Null")
		(when {
			hasExtra(argumentName) -> getBooleanExtra(argumentName, defaultValue as Boolean)
			extras?.containsKey(argumentName) == true -> extras?.getBoolean(argumentName)
			else -> null
		}) ?: defaultValue as Boolean
	}

	clazz == Double::class.java -> {
		if (defaultValue == null) throw Exception("错误：参数defaultValue不能为Null")
		(when {
			hasExtra(argumentName) -> getDoubleExtra(argumentName, defaultValue as Double)
			extras?.containsKey(argumentName) == true -> extras?.getDouble(argumentName)
			else -> null
		}) ?: defaultValue as Long
	}
	clazz == Float::class.java -> {
		if (defaultValue == null) throw Exception("错误：参数defaultValue不能为Null")
		(when {
			hasExtra(argumentName) -> getFloatExtra(argumentName, defaultValue as Float)
			extras?.containsKey(argumentName) == true -> extras?.getFloat(argumentName)
			else -> null
		}) ?: defaultValue as Long
	}
	clazz == Long::class.java -> {
		if (defaultValue == null) throw Exception("错误：参数defaultValue不能为Null")
		(when {
			hasExtra(argumentName) -> getLongExtra(argumentName, defaultValue as Long)
			extras?.containsKey(argumentName) == true -> extras?.getLong(argumentName)
			else -> null
		}) ?: defaultValue as Long
	}
	clazz == Int::class.java -> {
		if (defaultValue == null) throw Exception("错误：参数defaultValue不能为Null")
		(when {
			hasExtra(argumentName) -> getIntExtra(argumentName, defaultValue as Int)
			extras?.containsKey(argumentName) == true -> extras?.getInt(argumentName)
			else -> null
		}) ?: defaultValue as Int
	}
	clazz == Short::class.java -> {
		if (defaultValue == null) throw Exception("错误：参数defaultValue不能为Null")
		(when {
			hasExtra(argumentName) -> getShortExtra(argumentName, defaultValue as Short)
			extras?.containsKey(argumentName) == true -> extras?.getShort(argumentName)
			else -> null
		}) ?: defaultValue as Short
	}
	clazz == Char::class.java -> {
		if (defaultValue == null) throw Exception("错误：参数defaultValue不能为Null")
		(when {
			hasExtra(argumentName) -> getCharExtra(argumentName, defaultValue as Char)
			extras?.containsKey(argumentName) == true -> extras?.getChar(argumentName)
			else -> null
		}) ?: defaultValue as Char
	}
	clazz == Byte::class.java -> {
		if (defaultValue == null) throw Exception("错误：参数defaultValue不能为Null")
		(when {
			hasExtra(argumentName) -> getByteExtra(argumentName, defaultValue as Byte)
			extras?.containsKey(argumentName) == true -> extras?.getByte(argumentName)
			else -> null
		}) ?: defaultValue as Char
	}

	clazz == DoubleArray::class.java -> when {
		hasExtra(argumentName) -> getDoubleArrayExtra(argumentName)
		extras?.containsKey(argumentName) == true -> extras?.getDoubleArray(argumentName)
		else -> null
	}
	clazz == FloatArray::class.java -> when {
		hasExtra(argumentName) -> getFloatArrayExtra(argumentName)
		extras?.containsKey(argumentName) == true -> extras?.getFloatArray(argumentName)
		else -> null
	}
	clazz == LongArray::class.java -> when {
		hasExtra(argumentName) -> getLongArrayExtra(argumentName)
		extras?.containsKey(argumentName) == true -> extras?.getLongArray(argumentName)
		else -> null
	}
	clazz == IntArray::class.java -> when {
		hasExtra(argumentName) -> getIntArrayExtra(argumentName)
		extras?.containsKey(argumentName) == true -> extras?.getIntArray(argumentName)
		else -> null
	}
	clazz == ShortArray::class.java -> when {
		hasExtra(argumentName) -> getShortArrayExtra(argumentName)
		extras?.containsKey(argumentName) == true -> extras?.getShortArray(argumentName)
		else -> null
	}
	clazz == CharArray::class.java -> when {
		hasExtra(argumentName) -> getCharArrayExtra(argumentName)
		extras?.containsKey(argumentName) == true -> extras?.getCharArray(argumentName)
		else -> null
	}
	clazz == ByteArray::class.java -> when {
		hasExtra(argumentName) -> getByteArrayExtra(argumentName)
		extras?.containsKey(argumentName) == true -> extras?.getByteArray(argumentName)
		else -> null
	}
	clazz == BooleanArray::class.java -> when {
		hasExtra(argumentName) -> getBooleanArrayExtra(argumentName)
		extras?.containsKey(argumentName) == true -> extras?.getBooleanArray(argumentName)
		else -> null
	}

	Parcelable::class.java.isAssignableFrom(clazz) -> {
		when {
			hasExtra(argumentName) -> getParcelableExtra<Parcelable>(argumentName)
			extras?.containsKey(argumentName) == true -> extras?.getParcelable<Parcelable>(argumentName)
			else -> null
		}
	}

	clazz == ArrayList::class.java || clazz == List::class.java || clazz == MutableList::class.java || clazz == Collection::class.java -> when {
		componentClazz == Int::class.java -> getIntegerArrayListExtra(argumentName)
		componentClazz == String::class.java -> getStringArrayListExtra(argumentName)
		componentClazz == CharSequence::class.java -> getCharSequenceArrayExtra(argumentName)
		componentClazz != null && Parcelable::class.java.isAssignableFrom(componentClazz) -> getParcelableArrayListExtra<Parcelable>(argumentName)
		else -> null
	}

	else -> throw Exception("错误：参数clazz为不支持的数据类型")
}
